﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using System.Collections;
using System.Globalization;
using System.Reflection;

namespace CKS.SharePoint.Workbook {
    public partial class CreateCommunityControl : System.Web.UI.UserControl {
        protected void Page_Load(object sender, EventArgs e) {
            if (!Page.IsPostBack) {
                LoadData();
            }
        }

        private void LoadData() {
            SPWeb site = SPContext.Current.Web;

            // Default begin date.
            communityBeginDateDateTimeControl.SelectedDate = DateTime.Now;

            // Populate languages listbox
            SPLanguageCollection installedLanguages = site.RegionalSettings.InstalledLanguages;
            if (installedLanguages != null) {
                SortedList list = new SortedList(installedLanguages.Count);

                for (int i = 0; i < installedLanguages.Count; i++) {
                    SPLanguage language = installedLanguages[i];
                    list.Add(language.DisplayName, new ListItem(language.DisplayName, language.LCID.ToString()));
                }

                foreach (DictionaryEntry item in list) {
                    languageListBox.Items.Add((ListItem) item.Value);
                }
            } else {
                CultureInfo ci = new CultureInfo((int) site.Language);
                languageListBox.Items.Add(new ListItem(ci.NativeName, ci.LCID.ToString()));
            }
        }

        protected void languageListBox_SelectedIndexChanged(object sender, EventArgs e) {
            if (languageListBox.SelectedIndex < 0) {
                return;
            }

            SPWeb site = SPContext.Current.Web;

            // Populate categories listbox
            SPWebTemplateCollection templates = site.GetAvailableWebTemplates(uint.Parse(languageListBox.SelectedValue));

            if (templates != null) {
                SortedList list = new SortedList();

                foreach (SPWebTemplate template in templates) {
                    if (!template.IsHidden && !list.ContainsKey(template.DisplayCategory) && !template.IsRootWebOnly) {
                        list.Add(template.DisplayCategory, new ListItem(template.DisplayCategory, template.DisplayCategory));
                    }
                }

                categoryListBox.Items.Clear();
                foreach (DictionaryEntry item in list) {
                    categoryListBox.Items.Add((ListItem) item.Value);
                }
            }
        }

        protected void categoryListBox_SelectedIndexChanged(object sender, EventArgs e) {
            if (categoryListBox.SelectedIndex < 0) {
                return;
            }

            SPWeb site = SPContext.Current.Web;

            // Populate templates listbox
            SPWebTemplateCollection templates = site.GetAvailableWebTemplates(uint.Parse(languageListBox.SelectedValue));

            if (templates != null) {
                SortedList list = new SortedList();

                foreach (SPWebTemplate template in templates) {
                    if (!template.IsHidden && template.DisplayCategory == categoryListBox.SelectedValue && !template.IsRootWebOnly) {
                        list.Add(template.Title, new ListItem(template.Title, template.Name));
                    }
                }

                templateListBox.Items.Clear();
                foreach (DictionaryEntry item in list) {
                    templateListBox.Items.Add((ListItem) item.Value);
                }
            }
        }

        protected void cancelButton_Click(object sender, EventArgs e) {
            string sourceUrl = Request["Source"];

            if (string.IsNullOrEmpty(sourceUrl)) {
                sourceUrl = SPContext.Current.Web.ServerRelativeUrl;
            }

            Response.Redirect(sourceUrl);
        }

        protected void createButton_Click(object sender, EventArgs e) {
            using (SPLongOperation longOp = new SPLongOperation(this.Page)) {
                longOp.LeadingHTML = "Please wait while we create your community."; // TODO: Needs translation.
                longOp.Begin();

                string siteUrl = CreateSubSite();

                longOp.End(siteUrl);
            }
        }

        private string CreateSubSite() {
            SPSite currentSiteCollection = SPContext.Current.Site;
            string newSiteUrl = string.Empty;
            SPUser currentUser = currentSiteCollection.RootWeb.CurrentUser;

            SPSecurity.RunWithElevatedPrivileges(delegate() {
                using (SPSite fullControlSiteCollection = new SPSite(currentSiteCollection.ID)) {
                    // We are only creating group sites as subsites of the top-level site.
                    SPWeb topLevelSite = fullControlSiteCollection.RootWeb;

                    try {
                        topLevelSite.AllowUnsafeUpdates = true;

                        // Create the new site.
                        using (SPWeb newSite = topLevelSite.Webs.Add(
                                MakeSafeSiteName(communityNameTextBox.Text),
                                communityNameTextBox.Text,
                                communityDescriptionTextBox.Text,
                                uint.Parse(languageListBox.SelectedValue),
                                templateListBox.SelectedValue,
                                true,
                                false)) {

                            // Create default site groups.
                            Type type = typeof(Microsoft.SharePoint.SPWeb).Assembly.GetType("Microsoft.SharePoint.Utilities.SPUtilityInternal");
                            MethodInfo method = type.GetMethod("CreateDefaultSharePointGroups", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(Microsoft.SharePoint.SPWeb) }, null);
                            method.Invoke(null, new object[] { newSite });

                            // Add the current user as a owner.
                            SPUser newSiteUser = newSite.EnsureUser(currentUser.LoginName);
                            newSite.AssociatedOwnerGroup.AddUser(newSiteUser);

                            // Update user information.
                            newSiteUser.Email = currentUser.Email;
                            newSiteUser.Name = currentUser.Name;
                            newSiteUser.Update();

                            // Save the site url for later redirection.
                            newSiteUrl = newSite.ServerRelativeUrl;

                            // Create the value for the people picker column.
                            SPFieldUserValue userValue = new SPFieldUserValue(topLevelSite, currentUser.ID, currentUser.LoginName);

                            // Update communities list.
                            SPList communitiesList = topLevelSite.Lists["Communities"];

                            SPListItem item = communitiesList.Items.Add();
                            item["Title"] = communityNameTextBox.Text;
                            item["CommunityDescription"] = communityDescriptionTextBox.Text;
                            item["CommunityBeginDate"] = communityBeginDateDateTimeControl.SelectedDate;
                            if (!communityEndDateDateTimeControl.IsDateEmpty) {
                                item["CommunityEndDate"] = communityEndDateDateTimeControl.SelectedDate;
                            }
                            item["RelatedURL"] = newSiteUrl;
                            item["CommunityOwner"] = userValue;
                            item["Author"] = userValue;
                            item.Update();

                            // Activate community feature.
                            newSite.Features.Add(new Guid("4EB7A380-1B68-476C-BE39-6044A4A97D4C"));

                            // Update roles in the new site.
                            SPList rolesList = newSite.Lists["Roles"];
                            string[] roles = communityRolesTextBox.Text.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                            foreach (string role in roles) {
                                SPListItem roleItem = rolesList.Items.Add();
                                roleItem["Title"] = role;
                                roleItem.Update();

                                newSite.SiteGroups.Add(role, newSiteUser, null, string.Empty);
                            }
                        }
                    } finally {
                        topLevelSite.AllowUnsafeUpdates = false;
                    }
                }
            });

            return newSiteUrl;
        }

        private string MakeSafeSiteName(string siteName) {
            // TODO: Make the siteName safe to be a URL.
            return siteName;
        }
    }
}